Token optimization: reduce plugin overhead 55% and enforce Agent Teams#36
Conversation
Review Summary by QodoToken optimization: compress prompts, deduplicate agents, reduce context by 55-90K tokens/session
WalkthroughsDescription• Compress delegation error messages by 57% (single-line format, no emoji)
• Deduplicate agent definition boilerplate by 47% (640→339 lines across 8 agents)
• Slim workflow_orchestrator.md by 49% (1065→545 lines, consolidate rules)
• Compress /delegate template by 89% (4955→555 chars, reference orchestrator)
• Add partial file read guidance (offset/limit for >200 lines)
• Enforce DONE|{path} return format consistently across all agents
• Update documentation with token efficiency guidance and mandatory filler reduction rules
Diagramflowchart LR
A["Agent Definitions<br/>8 files"] -->|"Deduplicate boilerplate<br/>47% reduction"| B["Slim Agent Prompts<br/>339 lines each"]
C["Delegation Errors<br/>require_delegation.py"] -->|"Compress 57%<br/>single-line format"| D["Minimal Error Messages"]
E["Orchestrator Prompt<br/>1065 lines"] -->|"Slim 49%<br/>consolidate rules"| F["Compact Orchestrator<br/>545 lines"]
G["/delegate Template<br/>4955 chars"] -->|"Compress 89%<br/>reference orchestrator"| H["Minimal Template<br/>555 chars"]
I["CLI & File Reading"] -->|"Add partial read guidance<br/>offset/limit for >200 lines"| J["Token Efficient Guidance"]
B --> K["~55-90K tokens/session saved"]
D --> K
F --> K
H --> K
J --> K
File Changes1. hooks/PreToolUse/require_delegation.py
|
Code Review by Qodo
1. compact_run.py returns raw codes
|
|
/agentic_review |
|
Persistent review updated to latest commit 46215f7 |
|
/agentic_review |
|
Persistent review updated to latest commit 1ff8f0a |
5615e49 to
779bd1d
Compare
779bd1d to
762207d
Compare
## Conditional Orchestrator Injection
- SessionStart injects 40-line routing stub (~200 tokens) instead of
full 545-line orchestrator (~5.5K tokens)
- Full orchestrator loads on-demand via /delegate command only
- Sessions that don't use multi-step delegation save ~5K tokens
## Prompt Compression
- Orchestrator slimmed 49% (1065→545 lines)
- /delegate template compressed 89% (4955→555 chars)
- Agent definitions deduplicated 47% (640→339 lines)
- Delegation error messages compressed 57%, no emoji
## Token Efficiency Enhancements
- DONE|{path} return format enforced in all 8 agent definitions
- Partial file read guidance (offset/limit for >200 lines)
- cd && command pattern handling in rewrite hook
- Added eslint, next lint, tsc to output compression
- Conversation filler reduction rules in output style
## Agent Teams as Default
- Team mode detection via TeamCreate tool availability (not Bash env check)
- Mandatory TeamCreate + Agent(team_name=...) when teams available
- Isolated subagents only as fallback when TeamCreate fails
- Team check is FIRST ACTION before any planning
## Cleanup
- Deleted deprecated task-planner skill (-622 lines)
- Planning exclusively via native EnterPlanMode
- Updated all documentation (CLAUDE.md, README.md, docs/)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
762207d to
99dbd67
Compare
Change exit code from 0 (fail-open) to 1 (internal error) in the uncaught exception handler, per hook exit code convention: 0=allow, 1=error, 2=block. Addresses Qodo review feedback on PR #36.
|
/agentic_review |
Code Review by QodoNew Review StartedThis review has been superseded by a new analysisⓘ The new review experience is currently in Beta. Learn more |
|
/agentic_review |
|
Persistent review updated to latest commit 0e7dc8b |
| #!/usr/bin/env python3 | ||
| """ | ||
| SessionStart Hook: Inject workflow_orchestrator system prompt (cross-platform) | ||
| SessionStart Hook: Inject orchestrator routing stub (cross-platform) | ||
|
|
||
| This hook runs on session startup/resume/clear/compact and injects the | ||
| workflow_orchestrator.md system prompt into Claude's context. This enables | ||
| automatic multi-step workflow detection, phase decomposition, and intelligent | ||
| delegation orchestration for every session. | ||
| orchestrator_stub.md routing prompt into Claude's context. The full | ||
| workflow_orchestrator.md is loaded on-demand by /delegate. | ||
|
|
||
| This Python version works on Windows, macOS, and Linux. | ||
| """ | ||
|
|
||
| import io | ||
| import json | ||
| import logging | ||
| import os | ||
| import sys | ||
| import tempfile | ||
| from pathlib import Path |
There was a problem hiding this comment.
1. inject_workflow_orchestrator.py lacks pep723 📘 Rule violation ⚙ Maintainability
hooks/SessionStart/inject_workflow_orchestrator.py is executed via uv run --script but does not include a PEP 723 # /// script metadata block. This breaks the required standard for standalone script metadata and dependency declaration semantics.
Agent Prompt
## Issue description
`hooks/SessionStart/inject_workflow_orchestrator.py` is run via `uv run --script` but is missing the required PEP 723 inline metadata block.
## Issue Context
`hooks/plugin-hooks.json` invokes this hook using `uv run --no-project --script`, so it should include a PEP 723 block near the top (even if it has no third-party dependencies).
## Fix Focus Areas
- hooks/SessionStart/inject_workflow_orchestrator.py[1-18]
- hooks/plugin-hooks.json[81-99]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
|
||
| import io | ||
| import json | ||
| import logging | ||
| import os | ||
| import re | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| # Force UTF-8 output on Windows (fixes emoji encoding errors) | ||
| # Must run before any text I/O including logger StreamHandler setup | ||
| if sys.platform == "win32": | ||
| sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") | ||
| sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace") | ||
|
|
||
| # Configure logger for hook diagnostics (stderr so Claude Code captures it) | ||
| logger = logging.getLogger("require_delegation") | ||
| logger.setLevel(logging.WARNING) | ||
| _handler = logging.StreamHandler(sys.stderr) | ||
| _handler.setFormatter(logging.Formatter("%(message)s")) | ||
| logger.addHandler(_handler) | ||
|
|
There was a problem hiding this comment.
2. require_delegation.py lacks pep723 📘 Rule violation ⚙ Maintainability
hooks/PreToolUse/require_delegation.py is executed via uv run --script but does not include a PEP 723 # /// script metadata block. This violates the required standard for standalone script metadata.
Agent Prompt
## Issue description
`hooks/PreToolUse/require_delegation.py` is run via `uv run --script` but is missing the required PEP 723 inline metadata block.
## Issue Context
`hooks/plugin-hooks.json` invokes this hook using `uv run --no-project --script`, so it should include a PEP 723 block near the top (even if it has no third-party dependencies).
## Fix Focus Areas
- hooks/PreToolUse/require_delegation.py[1-35]
- hooks/plugin-hooks.json[12-18]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| - If two tasks in the same wave modify the same file → move one to the next wave | ||
| - If two tasks read the same file but only one writes → OK (parallel safe) | ||
| - If uncertain about file overlap → default to sequential (conservative) | ||
| **Decision:** ALWAYS set `execution_mode: "team"` in the plan when `TeamCreate` is available. The ONLY exception is breadth-only tasks where score <= -3. If TeamCreate fails at runtime, the fallback section handles it automatically. Without teams available: always parallel subagent (>=2 subtasks mandatory). |
There was a problem hiding this comment.
3. execution_mode ignores score threshold 📘 Rule violation ✓ Correctness
The updated orchestration instructions only allow subagent fallback for breadth-only tasks when team_mode_score <= -3, but the policy requires falling back to subagent mode whenever team_mode_score <= -3 with Agent Teams enabled. This can incorrectly force team mode even when the score indicates subagent fallback should be used.
Agent Prompt
## Issue description
The `team_mode_score` decision logic in `system-prompts/workflow_orchestrator.md` does not match the required behavior: when Agent Teams is enabled, subagent mode must be selected whenever `team_mode_score <= -3` (not only for breadth-only tasks).
## Issue Context
The compliance requirement mandates: team mode is default when the teams flag is enabled and `team_mode_score` is None/absent or > -3; subagent mode only when `team_mode_score <= -3`.
## Fix Focus Areas
- system-prompts/workflow_orchestrator.md[360-383]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| if second == "next": | ||
| if exit_code == 0: | ||
| print("ok \u2192 no issues") # noqa: T201 | ||
| return exit_code | ||
| return emit_failure(stdout, stderr, exit_code) | ||
|
|
There was a problem hiding this comment.
4. Npx next output suppressed 🐞 Bug ✓ Correctness
compact_run.handle_npx() treats any successful npx next <anything> as “no issues” and returns without printing stdout/stderr, so legitimate output is lost. token_rewrite_hook will wrap `npx next ... commands into compact_run.py`, making this suppression apply broadly whenever users run npx next successfully.
Agent Prompt
## Issue description
`hooks/compact_run.py` suppresses stdout/stderr for any successful `npx next ...` invocation because it only checks `args[1] == "next"`. This drops real output for commands like `npx next build`.
## Issue Context
`hooks/PreToolUse/token_rewrite_hook.py` wraps `npx next ...` into `compact_run.py`, so this behavior affects normal user workflows.
## Fix Focus Areas
- hooks/compact_run.py[257-296]
- hooks/PreToolUse/token_rewrite_hook.py[38-56]
- hooks/PreToolUse/token_rewrite_hook.py[73-89]
## Suggested changes
1. In `handle_npx`, only apply the `next` compression when the actual subcommand is `lint` (e.g., `len(args) > 2 and args[2] == "lint"`). Otherwise, fall through to passthrough printing.
2. Optionally, harden the pattern further by only emitting `ok → ...` when stdout/stderr are empty on success (so informational flags like `--version` don’t get erased).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| --- | ||
| description: Execute plan mode output by delegating phases to specialized agents | ||
| description: Plan and execute task via workflow orchestrator | ||
| argument-hint: [task description] | ||
| allowed-tools: Agent, Task | ||
| --- |
There was a problem hiding this comment.
5. Delegate allowlist inconsistent 🐞 Bug ⛯ Reliability
/delegate declares allowed-tools: Agent, Task but the command text requires EnterPlanMode/ExitPlanMode and Tasks API tools (TaskCreate/TaskUpdate/TaskGet/TaskList). This mismatch can prevent /delegate from executing its own flow in environments that enforce allowed-tools for slash commands.
Agent Prompt
## Issue description
`commands/delegate.md` declares `allowed-tools: Agent, Task` but the command’s own instructions require additional tools (EnterPlanMode, ExitPlanMode, TaskCreate/TaskUpdate/TaskGet/TaskList, and AskUserQuestion). If the runtime honors `allowed-tools`, `/delegate` cannot run as written.
## Issue Context
Other commands in this repo use `allowed-tools` to constrain behavior, so this metadata is likely meaningful and should match the command’s required tool calls.
## Fix Focus Areas
- commands/delegate.md[1-5]
- commands/delegate.md[179-186]
- commands/delegate.md[414-420]
## Suggested changes
Update the frontmatter `allowed-tools` list to include the tools the command requires (at minimum: `EnterPlanMode`, `ExitPlanMode`, `AskUserQuestion`, `TaskCreate`, `TaskUpdate`, `TaskGet`, `TaskList`, plus `Agent`/`Task` as needed), or adjust the body to avoid requiring tools not in the allowlist.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
… next output, delegate allowlist - Add PEP 723 inline metadata to inject_workflow_orchestrator.py and require_delegation.py - Fix execution_mode selection to fall back to subagent when team_mode_score <= -3 (not just breadth tasks) - Fix npx next output suppression: only compress 'next lint', pass through other next commands - Update delegate.md allowed-tools to include all required tools (EnterPlanMode, ExitPlanMode, TaskCreate, etc.)
|
/agentic_review |
Code Review by QodoNew Review StartedThis review has been superseded by a new analysisⓘ The new review experience is currently in Beta. Learn more |
…, < 5 for subagent) Aligns workflow_orchestrator.md team_mode_score decision logic with the documented policy in CLAUDE.md. The previous threshold (> -3) effectively restricted subagent fallback to breadth-only tasks. The correct threshold (>= 5) ensures subagent mode is selected whenever the score indicates insufficient complexity for team coordination.
|
/agentic_review |
Code Review by QodoNew Review StartedThis review has been superseded by a new analysisⓘ The new review experience is currently in Beta. Learn more |
Align execution mode selection policy so that team mode is the default when Agent Teams is enabled, falling back to subagent only when team_mode_score <= -3 (previously required score >= 5 to use teams). Updated both workflow_orchestrator.md and CLAUDE.md for consistency.
|
/agentic_review |
|
Persistent review updated to latest commit 79520e4 |
| if second == "next": | ||
| # Only compress 'next lint'; other next commands (build, dev, etc.) need their output | ||
| if len(args) > 2 and args[2] == "lint": | ||
| if exit_code == 0: | ||
| print("ok \u2192 no issues") # noqa: T201 | ||
| return exit_code | ||
| return emit_failure(stdout, stderr, exit_code) | ||
| # Fall through to passthrough for non-lint next commands | ||
| if stdout: | ||
| print(stdout) # noqa: T201 | ||
| if stderr: | ||
| print(stderr, file=sys.stderr) # noqa: T201 | ||
| return exit_code |
There was a problem hiding this comment.
1. compact_run.py returns raw codes 📘 Rule violation ⛯ Reliability
The updated npx next handling returns the underlying command exit_code directly, which can be values other than 0/1/2. Hook scripts must normalize exit codes to the standardized set to avoid unexpected hook behavior.
Agent Prompt
## Issue description
`hooks/compact_run.py` returns the wrapped command's raw `exit_code` (e.g., from `next`, `tsc`, or other tools). This can propagate non-standard exit codes (not limited to 0/1/2), violating the standardized hook exit-code contract.
## Issue Context
Compliance requires hook scripts to use only:
- `0` for success/allow
- `1` for unexpected/internal errors
- `2` only for deliberate blocks in PreToolUse hooks
Even though `compact_run.py` is used as part of the hook pipeline, it currently returns arbitrary exit codes.
## Fix Focus Areas
- hooks/compact_run.py[279-291]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| - `metadata`: Object with wave, phase, agent, parallel info, and `output_file: $CLAUDE_SCRATCHPAD_DIR/{sanitized_subject}.md` | ||
|
|
||
| **Agent Return Format (CRITICAL):** Return EXACTLY `DONE|{output_file_path}`. PROHIBITED: summaries, findings, any other text. All content goes in output file. |
There was a problem hiding this comment.
2. done|{output_file_path} return format 📘 Rule violation ✓ Correctness
The updated /delegate template instructs agents to return DONE|{output_file_path}, but
compliance requires the documented/configured completion format DONE|{output_file}. This
inconsistency can break completion parsing/enforcement that expects the standardized
placeholder/pattern.
Agent Prompt
## Issue description
The delegate template and agent instructions use `DONE|{output_file_path}` instead of the required `DONE|{output_file}` completion pattern.
## Issue Context
Downstream orchestration/parsing and compliance enforcement rely on a standardized `DONE|{output_file}` convention. Using a different placeholder name makes the completion contract inconsistent and potentially unparseable by consumers expecting `output_file`.
## Fix Focus Areas
- commands/delegate.md[294-296]
- agents/code-reviewer.md[9-12]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| "npx": ["vitest", "jest", "mocha", "playwright", "eslint", "next", "tsc"], | ||
| "go": ["test"], | ||
| "make": ["test", "check"], | ||
| "next": ["lint"], |
There was a problem hiding this comment.
3. Long-running npx wrapped 🐞 Bug ⛯ Reliability
token_rewrite_hook.py now wraps any npx next .../npx tsc .../npx eslint ... command based only on the second token, so long-running modes like npx next dev or npx tsc --watch will be routed through compact_run.py and can be terminated by its timeout. This changes command behavior (timeouts + no live streaming) rather than just compressing output.
Agent Prompt
## Issue description
`token_rewrite_hook.py` wraps all `npx next ...`, `npx tsc ...`, and `npx eslint ...` invocations, which unintentionally routes long-running/interactive commands (e.g., `npx next dev`, `npx tsc --watch`) through `compact_run.py`. Because `compact_run.py` captures output and enforces a default timeout, these commands can be terminated and won’t behave as intended.
## Issue Context
The `_should_wrap()` implementation only checks the first token (family) and second token (subcommand). For `npx`, that means it cannot distinguish `npx next lint` (desired) from `npx next dev` (undesired).
## Fix Focus Areas
- Update wrapping logic to be more granular for `npx` (e.g., parse with `shlex.split()` and inspect additional args):
- hooks/PreToolUse/token_rewrite_hook.py[38-89]
- Ensure only the intended subcommands are wrapped (suggested examples):
- `npx next lint` only (require third token == `lint`)
- `npx tsc` only when NOT watch mode (reject when args contain `--watch`/`-w`)
- `npx eslint` only when NOT watch mode (reject when args contain `--watch`)
- hooks/PreToolUse/token_rewrite_hook.py[106-170]
- (Optional) add tests for excluded long-running commands to prevent regressions:
- tests/test_token_rewrite_hook.py[1-220]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| @pytest.mark.parametrize("runner", ["eslint", "next"]) | ||
| def test_lint_runner_success( | ||
| self, | ||
| compact_run: ModuleType, | ||
| capsys: pytest.CaptureFixture[str], | ||
| runner: str, | ||
| ) -> None: | ||
| code = compact_run.handle_npx(["npx", runner, "."], "lint output\n", "", 0) | ||
| assert code == 0 # noqa: S101 | ||
| assert "no issues" in capsys.readouterr().out # noqa: S101 | ||
|
|
||
| @pytest.mark.parametrize("runner", ["eslint", "next"]) | ||
| def test_lint_runner_failure( | ||
| self, | ||
| compact_run: ModuleType, | ||
| capsys: pytest.CaptureFixture[str], | ||
| runner: str, | ||
| ) -> None: | ||
| code = compact_run.handle_npx(["npx", runner, "."], "errors\n", "lint err\n", 1) | ||
| assert code == 1 # noqa: S101 | ||
| assert "lint err" in capsys.readouterr().err # noqa: S101 |
There was a problem hiding this comment.
4. Incorrect next lint test 🐞 Bug ✓ Correctness
tests/test_compact_run.py asserts handle_npx(["npx","next","."]) prints "no issues", but the implementation only prints that for npx next lint (third arg must be lint). This test will fail and also doesn’t validate the actual npx next lint success path.
Agent Prompt
## Issue description
A new unit test intended to validate `npx next lint` uses the wrong argument vector (`["npx", "next", "."]`), but the implementation only treats `npx next lint` (with `lint` as the third token) as compressible.
## Issue Context
`compact_run.handle_npx()` has a specific branch for `second == "next"` and then checks `args[2] == "lint"` before emitting `ok → no issues`.
## Fix Focus Areas
- Update the test to call the correct command form for lint:
- tests/test_compact_run.py[500-520]
- Add a separate test to verify passthrough behavior for non-lint `npx next ...` (e.g., `npx next dev` or `npx next build`), asserting it does **not** emit `no issues`:
- tests/test_compact_run.py[500-548]
- Keep implementation behavior unchanged unless you also change wrapping rules:
- hooks/compact_run.py[279-291]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
- Remove plugin-based review approach (code-review@claude-code-plugins) that was not posting comments correctly - Use standard auto-detected review mode for pull_request events - Add missing permissions: issues: write, actions: read - Add additional_permissions for CI result reading - Use prompt input for review instructions instead of plugin skill invocation
Resolves CI linting failure caused by unformatted code.
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
Summary
Reduces plugin session-start overhead from ~20K to ~9K tokens (55% reduction) and makes Agent Teams the default execution mode.
Token Budget Impact
Key Changes
Files Changed (~20 files, net -1500 lines)
system-prompts/orchestrator_stub.md(new) — 40-line routing stubsystem-prompts/workflow_orchestrator.md— slimmed 49%commands/delegate.md— embeds full orchestrator on-demandagents/*.md(all 8) — deduplicated 47%hooks/PreToolUse/require_delegation.py— compressed errors, logginghooks/PreToolUse/token_rewrite_hook.py— cd&&, eslint/next/tschooks/compact_run.py— eslint/next/tsc handlersoutput-styles/technical-adaptive.md— filler reduction rulesskills/task-planner/— deletedTest plan
🤖 Generated with Claude Code